"use strict";
const { Console } = require('console');
var fs = require('fs');
const https = require('https');
const { off } = require('process');

let data = null;
let dataR = null;
var prefStartR = [256];
var prefStart = [256];
var prefEndR = [256];
var prefEnd = [256];
var endArr = [];
var addrArr = [];
var modeStr = ""
var stats = 0
var fileName = ""


var readBuf = function (len, off) {
    const buffer = Buffer.alloc(len);
    fs.readSync(data, buffer, 0, len, off);
    return buffer
}



var loadFile = function (filepath, mode) {
    modeStr = mode
    stats = fs.statSync(filepath).size
    fileName = filepath
    if (mode == "file") {
        data = fs.openSync(filepath,"r");
        for (var k = 0; k < 256; k++) {
            var i = k * 8 + 4;
            var dataStr = readBuf(8, i)
            prefStart[k] = dataStr.readUInt32LE(0);
            prefEnd[k] = dataStr.readUInt32LE(4);
        }
    }
    else {
        data = fs.readFileSync(filepath);
        var RecordSize = data.readUInt32LE(0);
        for (var k = 0; k < 256; k++) {
            var i = k * 8 + 4;
            prefStart[k] = data.readUInt32LE(i);
            prefEnd[k] = data.readUInt32LE(i + 4);
        }
    }
};



var Get = function (ip) {
    if (fs.statSync(fileName).size != stats) {
        loadFile(fileName,mode)
    }
	var ipArray = ip.split('.'), ipInt = ipToInt(ip), pref = parseInt(ipArray[0]);
	var low = prefStart[pref], high = prefEnd[pref];
	var cur = low == high ? low : Search(low, high, ipInt);
	if (cur==100000000){
		return null;		
	}
    return GetAddr(cur);
}


var Search = function (low, high, k) {
	var M = 0;
	while (low <= high) {
		var mid = Math.floor((low + high) / 2);
        var j = 2052 + (mid * 9);
        var endipNum = 0
        if (modeStr == "file") {
            var dataStr = readBuf(4, j);
            endipNum = dataStr.readUInt32LE(0);
        }
        else {
            endipNum = data.readUInt32LE(j)
        }
		if (endipNum >= k) {
			M = mid;
			if (mid === 0) {
				break;   //防止溢出
			}
			high = mid - 1;
		}
		else
			low = mid + 1;
	}
	return M
}

var GetAddr = function (cur) {
    var p = 2052 + (cur * 9);
    if (modeStr == "file"){
        var dataStr = readBuf(9, p)
        var offset = dataStr.readUInt32LE(4);
        var length = dataStr.readUInt8(8);//1 bit 无符号整型 
        var dataStr2 = readBuf(length, offset)
        return dataStr2.toString('utf-8');
    }else{
        var offset = data.readUInt32LE(p + 4)
        var length = data.readUInt8(p + 8);//1 bit 无符号整型 

        return data.slice(offset,offset + length).toString("utf-8")
    }
    
}

var ipToInt = function (ip) { return new Buffer(ip.split('.')).readUInt32BE(0) }

var update = function (inputPath, outputPath) {
    const file = fs.createWriteStream(outputPath);
    https.get(inputPath, (response) => {
    response.on('data', (chunk) => {
        file.write(chunk);
    });

    response.on('end', () => {
        file.end();
        console.log('download completed');
    });

    response.on('error', (err) => {
        console.error('download file failed:', err);
        file.close();
    });
    }).on('error', (err) => {
    console.error('request file failed:', err);
    });
}

exports.loadFile = function (file,mode) {
	if (data === null) {
		loadFile(file,mode);
	}
}

exports.get = Get;



